﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microhard.WeixinMP.Interfaces;
using System.Security.Cryptography;
using Microhard.WeixinMP.Models;
using Microhard.Core.Net;
using Microhard.Core.Security;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using System.Net;
using System.ServiceModel.Dispatcher;
using System.Web;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Microhard.WeixinMP.DataAccess;
using Microhard.Core;
using System.Collections.Specialized;


namespace Microhard.WeixinMP.Impls
{
    public class HandshakeImpl : IWeixinMP
    {
        public bool Handshake(WeixinHandshakeModel handshake)
        {
            var arr = new[] { handshake.token, handshake.timestamp, handshake.nonce }.OrderBy(z => z).ToArray();
            var arrString = string.Join("", arr);
            var sha1 = SHA1.Create();
            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            StringBuilder enText = new StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }

            return enText.ToString() == handshake.signature ? true : false;
        }


        public bool Login(string mpUsername, string mpPassword, IWeixinMPHtmlParser<WeixinFakeLogin_Result> parser, bool reLogin)
        {
            //如果缓存中与登录的cookie，则从缓存中取出
            WXCookieCacheOperator wco = new WXCookieCacheOperator();
            if (!reLogin)
            {
                var extWc = wco.GetFromCache(mpUsername);
                if (extWc != null)
                    return true;
            }
            else
            {
                //删除缓存中的登录信息
                wco.RemoveFormCache(new List<string> { mpUsername });
            }

            bool rtn = false;
            string url = "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN";
            string loginfromat = "username={0}&pwd={1}&imgcode=&f=json";
            //username=48482293%40qq.com&pwd=fc76c4a86c56becc717a88f651264622&imgcode=&f=json
            string loginParms = string.Format(loginfromat, HttpUtility.UrlEncode(mpUsername), MD5Enc.UserMd5(mpPassword).ToLower());
            var cookie = new CookieContainer();
            string back = null;
            try
            {
                back = HttpReader.HttpPost(url, loginParms, "https://mp.weixin.qq.com/", ref cookie);
            }
            catch (Exception ex)
            {
                Log.Error("IWexinMP.Login", ex);
            }
            //解析返回值为json
            if (!string.IsNullOrEmpty(back))
            {
                var obj = parser.ParseObject(back);
                string token = string.Empty;
                if (obj.ErrCode == "0" && string.IsNullOrEmpty(obj.ErrMsg) == false)
                {
                    var parms = HttpUtility.ParseQueryString(obj.ErrMsg);
                    token = parms["token"];

                    WeixinCookie wc = new WeixinCookie();
                    wc.Cookie = cookie;
                    wc.Token = token;
                    wco.UpdateCache(mpUsername, wc);
                    rtn = true;
                }
            }
            return rtn;
        }


        public List<WeixinUserModel> GetTop10User(string mpUsername, string mpPassword, IWeixinMPHtmlParser<List<WeixinUserBasicModel>> parser, IWeixinMPHtmlParser<WeixinUserModel> parseUserInfo, IWeixinMPHtmlParser<WeixinFakeLogin_Result> loginParser)
        {
            //从缓存中取出cookie
            List<WeixinUserModel> rtn = new List<WeixinUserModel>();
            WXCookieCacheOperator wco = new WXCookieCacheOperator();
            var wc = wco.GetFromCache(mpUsername);

            //获得列表用户
            string url = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize=10&pageidx=0&type=0&groupid=0&token={0}&lang=zh_CN";
            url = string.Format(url, wc.Token);


            var cookie = wc.Cookie;
            string html = HttpReader.HttpGet(url, ref cookie);
            var basic = parser.ParseObject(html);
            //获得用户详细信息
            var infoUrl = "https://mp.weixin.qq.com/cgi-bin/getcontactinfo";
            string infoParms = "token={1}&lang=zh_CN&t=ajax-getcontactinfo&fakeid={0}";
            foreach (var b in basic)
            {
                string parms = string.Format(infoParms, b.fakeId, wc.Token);
                string strUserInfo = HttpReader.HttpPost(infoUrl, parms, ref cookie);
                rtn.Add(parseUserInfo.ParseObject(strUserInfo));
            }
            return rtn;
        }


        public void SendMessage(string mpUsername, string mpPassword, string fakeID, string text, IWeixinMPHtmlParser<WeixinFakeSendResult> parser, IWeixinMPHtmlParser<WeixinFakeLogin_Result> loginParser, bool reLogin)
        {
            string url = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response&lang=zh_CN";
            //type=1&content=dddd&error=false&imgcode=&tofakeid=59122365&token=180904257&ajax=1
            string parms = "type=1&content={0}&error=false&tofakeid={1}&token={2}&ajax=1";
            WXCookieCacheOperator wco = new WXCookieCacheOperator();

            //是否需要强制重新登录
            if (reLogin)
            {
                if (!this.Login(mpUsername, mpPassword, loginParser, reLogin))
                {
                    Log.Error("IWeixinMP.Login", "登录失败");
                }
            }

            //从缓存中取出cookie
            WeixinCookie wc = wco.GetFromCache(mpUsername);
            CookieContainer cookie = null;
            if (wc != null)
            {
                cookie = wc.Cookie;
            }

            //发送
            var parmsToPost = string.Format(parms, HttpUtility.UrlEncode(text), fakeID, wc.Token);
            string rtn = null;
            string referer = "https://mp.weixin.qq.com/cgi-bin/singlesendpage?t=message/send&action=index&tofakeid={0}&token={1}&lang=zh_CN";
            referer = string.Format(referer, fakeID, wc.Token);
            try
            {
                rtn = HttpReader.HttpPost(url, parmsToPost, referer, ref cookie);
            }
            catch (Exception ex)
            {
                Log.Error("IWeixinMP.SendMessage", ex);
            }
            //发送结果检验
            if (!string.IsNullOrEmpty(rtn))
            {
                var result = parser.ParseObject(rtn);
                if (result.msg == "ok" && result.ret == "0")
                {
                    Log.Info("IWeixinMP.SendMessage", "发送成功");
                }
                else
                {
                    Log.Error("IWeixinMP.SendMessage,发送失败", rtn);
                    //登出
                    this.LogonOff(mpUsername);
                    //重新登录系统并发送
                    this.SendMessage(mpUsername, mpPassword, fakeID, text, parser, loginParser, true);
                }
            }
        }


        public bool RecordMessage(RequestServiceModel msg, string mpAccountUserName)
        {
            bool rtn = false;
            var db = new MicrohardWXEntities();
            var mp = db.MPAccounts.SingleOrDefault(w => w.UserName == mpAccountUserName);
            if (mp != null)
            {
                string content = msg.XDocument.ToString();
                try
                {
                    db.AddToMPMessages(new MPMessage
                    {
                        Content = content,
                        CreateTime = DateTime.Now,
                        IsReply = false,
                        MPAccountID = mp.WXMPID,
                        MsgDateTime = msg.MsgCreateTime,
                        MsgId = long.Parse(string.IsNullOrEmpty(msg.MsgId) == true ? "0" : msg.MsgId),
                        MsgType = msg.MsgType,
                        OpenID = msg.FromUserName,
                        MPContentID = Guid.NewGuid()
                    });
                    db.SaveChanges();
                    rtn = true;
                }
                catch (Exception ex)
                {
                    Log.Error("handshakeImpl.RecordMessage", ex);
                }
            }
            return rtn;
        }


        public string UploadImage(string mpUsername, string mpPassword, string fileName, byte[] image, IWeixinMPHtmlParser<WeixinUploadResult> resultParser)
        {
            WXCookieCacheOperator wco = new WXCookieCacheOperator();
            var wc = wco.GetFromCache(mpUsername);
            var cookie = wc.Cookie;

            string url = "https://mp.weixin.qq.com/cgi-bin/uploadmaterial?cgi=uploadmaterial&type=2&token={0}&t=iframe-uploadfile&lang=zh_CN&formId=file_from_1471723944606";
            url = string.Format(url, wc.Token);
            NameValueCollection nvc = new NameValueCollection();
            nvc.Add("formId", string.Empty);
            string rtn = HttpReader.HttpUploadFile(url, fileName, image, "uploadfile", "image/jpeg", nvc, ref cookie);
            return resultParser.ParseObject(rtn).FileID;
        }


        public List<WXMPMessageWithFakeIDModel> GetTop50Message(string mpUsername, string mpPassword, IWeixinMPHtmlParser<List<WXMPMessageWithFakeIDModel>> resultParser)
        {
            WXCookieCacheOperator wco = new WXCookieCacheOperator();
            var wc = wco.GetFromCache(mpUsername);
            var cookie = wc.Cookie;
            List<WXMPMessageWithFakeIDModel> rtn = new List<WXMPMessageWithFakeIDModel>();

            string url = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&count=20&day=7&token={0}&lang=zh_CN";

            url = string.Format(url, wc.Token);
            string txt = null;
            try
            {
                txt = HttpReader.HttpGet(url, ref cookie);
            }
            catch (Exception ex)
            {
                Log.Error("IWeixinMP.GetMessage", ex);
            }

            if (!string.IsNullOrEmpty(txt))
            {
                rtn = resultParser.ParseObject(txt);
            }
            return rtn;
        }


        public void UpdateMsgCheckingStatus(List<Guid> msgID)
        {
            var db = new MicrohardWXEntities();
            var msgs = from m in db.MPMessages
                       from i in msgID
                       where m.MPContentID == i
                       select m;
            foreach (var m in msgs)
            {
                m.IsCheck = true;
            }
            try
            {
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                Log.Error("UpdateMsgCheckingStatus", ex);
            }
        }



        public void LogonOff(string mpUsername)
        {
            string loginOffUrl = "https://mp.weixin.qq.com/cgi-bin/logout?t=wxm-logout&token={0}&lang=zh_CN";
            WXCookieCacheOperator wco = new WXCookieCacheOperator();
            var wc = wco.GetFromCache(mpUsername);
            var cookie = wc.Cookie;
            string url = string.Format(loginOffUrl, wc.Token);
            try
            {
                HttpReader.HttpGet(url, ref cookie);
            }
            catch (Exception ex)
            {
                Log.Error("IWeixinMP.LogonOff", ex);
            }
        }


        public bool HasFakeID(string weixinName)
        {
            var db = new MicrohardWXEntities();
            var cnt = db.MPUsers.SingleOrDefault(u => u.OpenID == weixinName);
            if (cnt == null)
                return false;
            if (string.IsNullOrEmpty(cnt.FakeID))
                return false;
            return true;
        }
    }
}
